home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 24 / CU Amiga Magazine's Super CD-ROM 24 (1998)(EMAP Images)(GB)(Track 1 of 2)[!][issue 1998-07].iso / CUCD / Programming / SWI / source / src / test / mmap.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-11-12  |  7.7 KB  |  418 lines

  1. /*  $Id: mmap.c,v 1.9 1997/11/12 14:21:29 jan Exp $
  2.  
  3.     Designed and implemented by Jan Wielemaker
  4.     E-mail: jan@swi.psy.uva.nl
  5.  
  6.     Copyright (C) 1994 University of Amsterdam. All rights reserved.
  7. */
  8.  
  9. #ifdef HAVE_CONFIG_H
  10. #include <config.h>
  11. #endif
  12.  
  13. #include <stdio.h>
  14. #include <signal.h>
  15. #include <sys/mman.h>
  16. #include <fcntl.h>
  17. #include <errno.h>
  18. #ifdef HAVE_UNISTD_H
  19. #include <unistd.h>
  20. #endif
  21.  
  22. #ifndef FALSE
  23. #define FALSE 0
  24. #define TRUE 1
  25. #endif
  26.  
  27. #if !defined(MAP_ANON) && defined(MAP_ANONYMOUS)
  28. #define MAP_ANON MAP_ANONYMOUS
  29. #endif
  30.  
  31. #ifndef SIGRETTYPE
  32. #define SIGRETTYPE void
  33. #endif
  34.  
  35. #ifdef NEED_DECL_ERRNO
  36. extern int errno;
  37. #endif
  38.  
  39. int    mapfd;                /* map this one */
  40. int    pagsiz;                /* pagesize */
  41. void *  wraddr;                /* current address */
  42. int    provides_address = 1;        /* assume */
  43.  
  44. #define ulong unsigned long        /* avoid redefinition */
  45.  
  46. #define KB * 1024
  47. #define MB KB KB
  48.  
  49. #define RoundUp(x, y)    ((x)%(y) == 0 ? (x) : ((x)|((y)-1))+1)
  50. #define RoundDown(p, n)    ((p) & ~((n)-1))
  51. #define min(x, y)    ((x) < (y) ? (x) : (y))
  52. #define max(x, y)    ((x) > (y) ? (x) : (y))
  53.  
  54. typedef SIGRETTYPE (*handler_t)(int signal);
  55.  
  56. #ifdef MAP_ANON
  57. #define get_map_fd() (-1)
  58. #define STACK_MAP_TYPE MAP_ANON|MAP_PRIVATE|MAP_FIXED
  59. #else
  60. #define STACK_MAP_TYPE MAP_PRIVATE|MAP_FIXED
  61.  
  62. static int
  63. get_map_fd()
  64. { int fd;
  65.   static char *map = "/tmp/pl-map";
  66.  
  67.   if ( (fd = open("/dev/zero", O_RDONLY)) >= 0 )
  68.     return fd;
  69.  
  70.   if ( (fd = open(map, O_RDONLY)) < 0 )
  71.   { if ( errno == ENOENT )
  72.     { char buf[1024];
  73.       char *s;
  74.       int n;
  75.       int oldmask = umask(0);
  76.  
  77.       if ( (fd = open(map, O_RDWR|O_CREAT, 0666)) < 0 )
  78.       { perror(map);
  79.         exit(1);
  80.       }
  81.       umask(oldmask);
  82.       for(n=1024, s = buf; n > 0; n--)
  83.         *s++ = '\0';
  84.       for(n=pagsiz/1024; n > 0; n--)
  85.       { if ( write(fd, buf, 1024) != 1024 )
  86.     { perror(map);
  87.       exit(1);
  88.     }
  89.       }
  90.  
  91.       return fd;
  92.     }
  93.     
  94.     perror(map);
  95.     exit(1);
  96.   }
  97. }
  98. #endif /*MAP_ANON*/
  99.  
  100.  
  101. SIGRETTYPE
  102. segv_handler(int s, int type, void *scp, char *sigaddr)
  103. { ulong addr = RoundDown((ulong)wraddr, pagsiz);
  104.  
  105.   if ( sigaddr != wraddr )
  106.     provides_address = 0;
  107.  
  108.   if ( mmap((void *) addr, pagsiz,
  109.         PROT_READ|PROT_WRITE,
  110.         STACK_MAP_TYPE|MAP_FIXED,
  111.         mapfd, 0L) != (void *)addr )
  112.   { perror("mmap");
  113.     exit(1);
  114.   }
  115. #ifdef VERBOSE
  116.   printf("+"); fflush(stdout);
  117. #endif
  118.  
  119. #ifndef BSD_SIGNALS
  120.   signal(SIGSEGV, (handler_t) segv_handler);
  121. #endif
  122. }
  123.  
  124.  
  125. static int
  126. test_map(int *low)
  127. { int size = 40 KB;
  128.   int n;
  129.  
  130. #ifdef VERBOSE
  131.   printf("\nwrite-test from %p\n", low);
  132. #endif
  133.   for(n=0; n<size; n++)
  134.   { wraddr = &low[n];
  135.     low[n] = n;
  136.   }
  137. #ifdef VERBOSE
  138.   printf("\nread-test ... "); fflush(stdout);
  139. #endif
  140.   for(n=0; n<size; n++)
  141.   { if ( low[n] != n )
  142.     { fprintf(stderr, "Read bad value at %d: %d\n", n, low[n]);
  143.       return FALSE;
  144.     }
  145.   }
  146. #ifdef VERBOSE
  147.   printf("ok\n");
  148. #endif
  149.   return TRUE;
  150. }
  151.  
  152.  
  153. #ifndef HAVE_GETPAGESIZE
  154. #ifdef _SC_PAGESIZE
  155. int
  156. getpagesize()
  157. { return sysconf(_SC_PAGESIZE);
  158. }
  159. #else /*_SC_PAGESIZE*/
  160.  
  161. #if hpux
  162. #include <a.out.h>
  163. int
  164. getpagesize()
  165. {  
  166. #ifdef EXEC_PAGESIZE
  167.   return EXEC_PAGESIZE;
  168. #else
  169.   return 4096;                /* not that important */
  170. #endif
  171. }
  172. #endif /*hpux*/
  173. #endif /*_SC_PAGESIZE*/
  174. #endif /*HAVE_GETPAGESIZE*/
  175.  
  176.  
  177.          /*******************************
  178.          *      TOP OF THE HEAP    *
  179.          *******************************/
  180.  
  181. #ifdef HAVE_GETRLIMIT
  182. #ifdef HAVE_SYS_TIME_H
  183. #include <sys/time.h>
  184. #endif
  185. #ifdef HAVE_SYS_RESOURCE_H
  186. #include <sys/resource.h>
  187. #endif
  188.  
  189. #ifdef RLIMIT_DATA
  190. ulong
  191. topOfHeap(ulong heap_base)
  192. { struct rlimit limit;
  193.  
  194.   if ( getrlimit(RLIMIT_DATA, &limit) == 0 )
  195.   { ulong top = limit.rlim_cur + heap_base;
  196.  
  197. #ifdef VERBOSE
  198.     printf("Heap: %p ... %p\n", (void *)heap_base, (void *)top);
  199. #endif
  200.     return top;
  201.   }
  202.  
  203.   return 0L;
  204. }
  205. #else
  206. #define topOfHeap() (0L)
  207. #endif /*RLIMIT_DATA*/
  208. #else
  209. #define topOfHeap() (0L)
  210. #endif /*HAVE_GETRLIMIT*/
  211.  
  212.  
  213.          /*******************************
  214.          *           MAIN        *
  215.          *******************************/
  216.  
  217. static int
  218. testarea(ulong base, ulong top)
  219. { ulong step = 8 * pagsiz;
  220.   ulong addr;
  221.  
  222. #ifdef VERBOSE
  223.   printf("Testing area %p ... %p\n", base, top);
  224. #endif
  225.  
  226.   for(addr=base; addr<top; addr += step)
  227.   {
  228. #if VERBOSE >= 2
  229.     printf("%p ... ", addr); fflush(stdout);
  230. #else
  231. #ifdef VERBOSE
  232.     if ( ((addr-base)/step) % 64 == 0 )
  233.     { printf("\n%p ", addr);
  234.       fflush(stdout);
  235.     }
  236. #endif
  237. #endif
  238.  
  239.     if ( (ulong) mmap((void *) addr, pagsiz,
  240.               PROT_READ|PROT_WRITE, STACK_MAP_TYPE,
  241.               mapfd, 0L) == addr )
  242.     {
  243. #if VERBOSE >= 2
  244.       printf("ok\n");
  245. #else
  246. #ifdef VERBOSE
  247.       printf("."); fflush(stdout);
  248. #endif
  249. #endif
  250.       if ( munmap((void *) addr, pagsiz) != 0 )
  251.       { perror("munmap");
  252.     return FALSE;
  253.       }
  254.     } else
  255.     {
  256. #ifdef VERBOSE
  257.       char msg[1024];
  258.       sprintf(msg, "Failed to map at %p", addr);
  259.       perror(msg);
  260. #endif
  261.       return FALSE;
  262.     }
  263.   }
  264.  
  265.   signal(SIGSEGV, (handler_t) segv_handler);
  266.  
  267.   return test_map((int *)base);
  268. }
  269.  
  270.  
  271. static void
  272. ok()
  273. { printf("MMAP_STACK=1;\n");
  274.  
  275.   if ( provides_address )
  276.     printf("SIGNAL_HANDLER_PROVIDES_ADDRESS=1;\n");
  277.   if ( mapfd == -1 )
  278.     printf("HAVE_MAP_ANON=1;\n");
  279. }
  280.  
  281.  
  282. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  283. run_testarea() runs testarea as a child, 
  284.  
  285. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  286.  
  287. #if defined(HAVE_SYS_RESOURCE_H)
  288. #include <sys/resource.h>
  289. #endif
  290. #if defined(HAVE_SYS_WAIT_H) || defined(UNION_WAIT)
  291. #include <sys/wait.h>
  292. #endif
  293.  
  294. #ifdef UNION_WAIT
  295.  
  296. #define wait_t union wait
  297.  
  298. #ifndef WEXITSTATUS
  299. #define WEXITSTATUS(s) ((s).w_status)
  300. #endif
  301. #ifndef WTERMSIG
  302. #define WTERMSIG(s) ((s).w_status)
  303. #endif
  304.  
  305. #else /*UNION_WAIT*/
  306.  
  307. #define wait_t int
  308.  
  309. #ifndef WEXITSTATUS
  310. # define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
  311. #endif
  312. #ifndef WIFEXITED
  313. # define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
  314. #endif
  315.  
  316. #endif /*UNION_WAIT*/
  317.  
  318.  
  319. static int
  320. run_testarea(ulong base, ulong top)
  321. { pid_t pid;
  322.  
  323.   if ( (pid = fork()) == 0 )
  324.   { if ( testarea(base, top) )        /* the child */
  325.     { ok();
  326.       exit(0);
  327.     }
  328.   } else if ( pid < 0 )
  329.   { perror("fork");
  330.     exit(1);
  331.   } else                /* wait for it */
  332.   { wait_t status;
  333.     int n;
  334.  
  335.     while((n = wait(&status)) != -1 && n != pid);
  336.     if ( n == -1 )
  337.     { perror("wait");
  338.       exit(1);
  339.     }
  340.     if ( WIFEXITED(status) )
  341.       return WEXITSTATUS(status) == 0 ? TRUE : FALSE;
  342.  
  343.     return FALSE;            /* signalled */
  344.   }
  345. }
  346.  
  347. #define DEFSTACKSIZE (64 MB * 3 + 8 MB)
  348.  
  349. int
  350. main(int argc, char **argv)
  351. { ulong top, htop;
  352.   ulong base;
  353.   ulong hbase;
  354.   ulong stack;
  355.   ulong defsize = DEFSTACKSIZE;        /* Thats what we want */
  356.   ulong size;            
  357.   int tried = 0;
  358.  
  359.   pagsiz = getpagesize();
  360.   mapfd  = get_map_fd();
  361.   hbase  = RoundDown((ulong)sbrk(0) + 8 MB, pagsiz);
  362.   htop   = topOfHeap(hbase);
  363.  
  364.   if ( htop )
  365.     defsize = size = min(htop-(hbase+1 MB), DEFSTACKSIZE);
  366.   else
  367.     defsize = size = DEFSTACKSIZE;
  368.  
  369. again:
  370.   if ( htop )                /* try from the top ... */
  371.   { top  = RoundDown(htop, pagsiz);
  372.     base = top - size;
  373.  
  374.     base = max(base, hbase);
  375.     if ( run_testarea(base, top) )
  376.     { if ( size != DEFSTACKSIZE )
  377.     printf("MMAP_STACKSIZE=%d;\n", size/(1 MB));
  378.       exit(0);                /* done */
  379.     }
  380.   }
  381.  
  382.   base = hbase;                /* failed, lets try from the bottom */
  383.   top = base + size;
  384.   if ( htop )
  385.     top = min(top, htop);
  386.   stack = (ulong)⊤            /* do not overwrite the stack */
  387.   if ( stack > base )
  388.   { ulong stack_base;
  389.  
  390.     if ( STACK_DIRECTION < 0 )
  391.       stack_base = RoundDown(stack - 8 MB, pagsiz);
  392.     else
  393.       stack_base = RoundDown(stack, 64 KB);
  394.  
  395.     top = min(top, stack_base);
  396.   }
  397.   size = top-base;
  398.  
  399.   if ( run_testarea(base, top) )
  400.   { if ( size != defsize )
  401.       printf("MMAP_STACKSIZE=%d;\n", size/(1 MB));
  402.     if ( htop )
  403.       printf("TOPOFHEAP=0;\n");
  404.     exit(0);
  405.   }
  406.  
  407.   if ( !tried++ )
  408.   {
  409. #if defined(__NetBSD__) && _MACHINE == amiga
  410.     size = 120 MB;
  411.     goto again;
  412. #endif
  413.   }
  414.  
  415.  
  416.   exit(1);
  417. }
  418.